#include <iostream>
#include <pthread.h>
using namespace std;
/*
各线程在堆和全局区共享的数据叫临界区，那么就会有数据竞争问题，引入互斥锁机制

    1、创建一个互斥锁：只需定义一个pthread_mutex_t 类型的变量即创建了一个互斥锁
    pthread_mutex_t mutex;

    2、初始化互斥锁
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //静态初始化

    int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
    功能：动态初始化互斥锁变量(动静态初始化跟静态常量与常量一样，一个编译时候完成，一个运行时候完成，静态的不需要销毁)
    参数1：互斥锁变量的地址，属于地址传递
    参数2：互斥锁属性，一般填NULL，让系统自动设置互斥锁属性
    返回值：成功返回0，失败返回错误码

    3、获取锁资源
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    功能：获取锁资源,如果要获取的互斥锁已经被其他线程锁定，那么该函数会阻塞，直到能够获取锁资源
    参数：互斥锁地址，属于地址传递
    返回值：成功返回0，失败返回一个错误码

    4、释放锁资源
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    功能：释放对互斥锁资源的拥有权
    参数：互斥锁变量的地址
    返回值：成功返回0，失败返回一个错误码

    5、销毁互斥锁
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    功能：销毁互斥锁
    参数：互斥锁变量的地址
    返回值：成功返回0，失败返回一个错误码

*/

int num = 520;         // 临界资源
pthread_mutex_t mutex; // 创建互斥锁

void *task(void *arg)
{

    pthread_mutex_lock(&mutex); // 先获取锁资源
    num = -10;                  // 临界区
    printf("子线程num=%d\n", num);
    // sleep(1);     //不要轻易在临界区sleep,可能其他线程就一直拿不到锁权了
    pthread_mutex_unlock(&mutex); // 释放锁资源
    return NULL;
}

int main(int argc, const char *argv[])
{
    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);
    // 创建子线程
    pthread_t tid = -1;
    if (pthread_create(&tid, NULL, task, NULL) != 0)
    {
        printf("tid create error\n");
        return -1;
    }

    pthread_mutex_lock(&mutex); // 先获取锁资源
    num += 100;                 // 临界区
    printf("主线程num=%d\n", num);
    pthread_mutex_unlock(&mutex); // 释放锁资源

    pthread_join(tid, NULL);       // 等待子线程结束
    pthread_mutex_destroy(&mutex); // 销毁互斥锁
}
